package com.cc8w.admin.controller;

import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationException;
import org.apache.shiro.config.IniSecurityManagerFactory;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.util.Factory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.cc8w.shiro.ShiroRealm;

@Controller
@RequestMapping("/admin/login")
public class LoginController extends BaseController {
	
    private static Logger logger = Logger.getLogger(LoginController.class);

    @Autowired
    private ShiroRealm shiroRealm;
	
	@RequestMapping("/index")
	public String index() {
		
		
		System.out.println("/admin/login/index");
		return "/admin/login/index";
	}
	
	/**
	 * 第一种登录验证方式
	 * @param username
	 * @param password
	 * @return
	 */
	@RequestMapping("/login")
	public String login(
			@RequestParam(value="username",defaultValue = "") String username,
			@RequestParam(value="password",defaultValue = "") String password) {
		/**
		 * 已经把xml配置文件改写成配置类：ShiroConfig
         * authc登录拦截器工作原理 (重点：xml过滤链不用排除login) 
         * authc拦截器有2个作用：
         * 1>登录认证
         *     请求进来时，拦截并判断当前用户是否登录了，如果已经登录了放行， 如果没有登录，跳转到authc.loginUrl属性配置的路径，注意：默认是/login.jsp
         *
         * 2>执行登录认证
         *     请求进来时，如果请求的路径为authc.loginUrl属性配置的路径（没配置，默认是/login.jsp）时，如果当前用户没有登录，authc这个拦截器会尝试获取请求中的账号跟密码值，然后比对ini配置文件或者realm中的用户列表，如果比对正确，直接执行登录操作，反之，抛异常，跳转到authc.loginUrl指定的路径。
         * 注意：请求中账号与密码必须固定为username 跟password， 如果需要改动必须额外指定，authc.usernameParam=xxx   authc.passwordParam=xxxx
         */
		
		
		//如果登录失败从request中获取认证信息，shiroLoginFailure就是shiro异常类的全限定名
        String exceptionClassName = (String) this.request.getAttribute("shiroLoginFailure");
        //根据shiro返回的异常类路径判断，抛出指定异常信息
        if(exceptionClassName!=null){
            //最终会抛出异常处理器
            if(UnknownAccountException.class.getName().equals(exceptionClassName)){
                this.request.setAttribute("errorMsg","账号不存在");
            }else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)){
                this.request.setAttribute("errorMsg","用户名/密码错误");
            }else{
                this.request.setAttribute("errorMsg","其他异常信息");
            }
        }
        //1.此方法不处理登录成功（认证成功），shiro认证成功会自动跳转到上一个请求路径
        //2.登录失败还到login页面
        //return "forward:/sys/admin/login";

		System.out.println("admin/login/login");
		return "admin/login/login";
	}
	
	/**
	 * 第二种登录验证方式
	 * @return
	 */
	@RequestMapping("/login2")
	public String login2(
			@RequestParam(value="username",defaultValue = "") String username,
			@RequestParam(value="password",defaultValue = "") String password) {
		
		
		//1.创建一个安全管理器的工厂
        //Factory<SecurityManager> factory = new IniSecurityManagerFactory();
        //2.在工厂中获取安全管理器
        //DefaultSecurityManager securityManager = (DefaultSecurityManager) factory.getInstance();
		//(new)1.直接获得安全管理器
        DefaultSecurityManager securityManager = new DefaultSecurityManager();
        
        //2.1 创建自定义Realm注入到安全管理器
        //ShiroRealm shiroRealm = new ShiroRealm();//(SpringM在bean控制,xml也可以配置散列加密相关)
        securityManager.setRealm(shiroRealm);

        //3.将securityManager绑定到运行环境
        SecurityUtils.setSecurityManager(securityManager);
        //4.获取Subject对象(将要登录的用户)
        Subject subject = SecurityUtils.getSubject();
        //5.获取要登录用户的token,客户端传递过来的用户名和密码
        //String username = "zhangsan",password="123456";
        UsernamePasswordToken token = new UsernamePasswordToken(username,password);
		
        try {
            //进行验证，这里可以捕获异常，然后返回对应信息
            subject.login(token);
//            subject.checkRole("admin");
//            subject.checkPermissions("query", "add");
        } catch (UnknownAccountException e) {
        	logger.error("用户名不存在！", e);
            return "用户名不存在！";
        } catch (AuthenticationException e) {
        	logger.error("账号或密码错误！", e);
            return "账号或密码错误！";
        } catch (AuthorizationException e) {
        	logger.error("没有权限！", e);
            return "没有权限";
        }
        return "login/success";
		
	}
	
	
	

}
